﻿using FlappyGame.View.ViewEx;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace FlappyGame.View
{
    public class PlayMap : Control
    {
        private System.Timers.Timer _timer;
        public PlayMap()
        {
            SetStyle(
             ControlStyles.ResizeRedraw
             | ControlStyles.DoubleBuffer
             | ControlStyles.UserPaint
             | ControlStyles.AllPaintingInWmPaint
             | ControlStyles.SupportsTransparentBackColor,
             true
             );

            _timer = new System.Timers.Timer();
            _timer.Interval = 10;
            _timer.Elapsed += _timer_Elapsed;
        }
        private int _step = 1;
        public int Step
        {
            get { return _step; }
            set { _step = value; }
        }
        const int PADDINGLEFT = 100;
        List<Pole> _data;
        int _birdX = 0;
        int _birdY = 0;
        public event Action GameStopCallback;
        private void _timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            // 改变位置
            for (int i = 0; i < _data.Count; i++)
            {
                var p = _data[i];
                p.Change(_step);
            }
            var first = _data[0];
            if (first.Top.X+ first.Top.Width < 0)
            {
                _data.Remove(first);
            }
            var last = _data.Last();
            if (last.Top.X <= 850)
            {
                var p = _poles.GetPole(last.Top.X + PADDINGLEFT, this.Height);
                _data.Add(p);
            }
            _birdY += 1;

           
            this.Invalidate();
        }
       
        public void Start()
        {
            lock (this)
            {
                _data = new List<Pole>();
                var startX = this.Width >> 1;
                for (int i = 0; i < 5; i++)
                {
                    var p = _poles.GetPole(startX, this.Height);
                    _data.Add(p);
                    startX += PADDINGLEFT;
                }
                _birdX = (this.Width >> 1) - 150;
                _birdY = (this.Height - __birdSize >> 1);
                this.Invalidate();
                _timer.Start();
            }
        }
        public void Stop()
        {
            _timer.Stop();
        }
        private Bitmap _mapBackground;
        private IntPtr _mapBackgroundPtr = IntPtr.Zero;
        public Bitmap MapBackground
        {
            get { return _mapBackground; }
            set
            {
                if (_mapBackgroundPtr != IntPtr.Zero)
                {
                    _mapBackground.Dispose();
                    GDI32.DeleteObject(_mapBackgroundPtr);
                    _mapBackgroundPtr = IntPtr.Zero;
                }
                _mapBackground = value;
                if (_mapBackground != null)
                    _mapBackgroundPtr = _mapBackground.GetHbitmap();
                this.Invalidate();
            }
        }
        private Bitmap _bird;
        private IntPtr _birdPtr = IntPtr.Zero;
        public Bitmap Bird
        {
            get { return _bird; }
            set
            {
                if (_birdPtr != IntPtr.Zero)
                {
                    _bird.Dispose();
                    GDI32.DeleteObject(_birdPtr);
                    _birdPtr = IntPtr.Zero;
                }
                _bird = value;
                if (_bird != null)
                    _birdPtr = _bird.GetHbitmap();
                this.Invalidate();
            }
        }
        private int __birdSize = 64;
        public int BirdSize
        {
            get { return __birdSize; }
            set
            {
                if (value < 16 || value == __birdSize) return;
                __birdSize = value;
                this.Invalidate();
            }
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            Stopwatch sw = Stopwatch.StartNew();
            e.Graphics.Smooth();

            IntPtr hdc = e.Graphics.GetHdc();
            // 绘制背景
            DrawBackground(hdc);
            // 绘制鸟
            DrawBird(hdc);
            e.Graphics.ReleaseHdc(hdc);

            // 绘制障碍物
            DrawObstacle(e.Graphics);
            e.Graphics.Smooth(false);
            // 判断碰撞
            if (_data !=null && !IsCollision())
            {
            }
            sw.Stop();
            Trace.WriteLine(sw.ElapsedMilliseconds);
        }
        protected override void OnSizeChanged(EventArgs e)
        {
            this.Invalidate();
        }
        private void DrawBackground(IntPtr hdc)
        {
            if (_mapBackgroundPtr != IntPtr.Zero)
            {
                GDI32.DrawImage2(hdc, _mapBackgroundPtr, 0, 0, _mapBackground.Width, _mapBackground.Height, this.Width, this.Height);
                //e.Graphics.DrawImage(_mapBackground, 0, 0, this.Width, this.Height);
            }
        }
        private void DrawBird(IntPtr hdc)
        {
            if (_birdPtr != IntPtr.Zero && _birdX != 0)
            {
                GDI32.DrawImageTransparenc(hdc, _birdPtr, _birdX, _birdY, _bird.Width, _bird.Height, BirdSize, BirdSize);
                //e.Graphics.DrawImage(_bird, _birdX, _birdY, __birdSize, __birdSize);
            }
        }
        private void DrawObstacle(Graphics g)
        {
            if (_data != null)
            {
                for (int i = 0; i < _data.Count; i++)
                {
                    var p = _data[i];
                    _poles.DrawGradientTop(g, p.Top);
                    _poles.DrawGradientBottom(g, p.Bottom);
                }
            }
        }
        private bool IsCollision()
        {
            int size = (int)(BirdSize / 3f);
            // 判断碰撞
            if (_poles.IsCollision(_birdX + size, _birdY + size, size, _data))
            {
                Stop();
                if (GameStopCallback != null)
                {
                    Task.Factory.StartNew(() =>
                    {
                        GameStopCallback();
                    });
                }
                return true;
            }
            return false;
        }
        protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
        {
            if (keyData == Keys.Space)
            {
                _birdY -= 20;
                return true;
            }
            return base.ProcessCmdKey(ref msg, keyData);
        }
        Poles _poles = new Poles();
        protected override void Dispose(bool disposing)
        {
            base.Dispose(disposing);
            _poles.Dispose();
        }
    }
}
